package com.kexuexiong.demo.bear.common.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import com.kexuexiong.demo.bear.common.config.MinioConfiguration;
import io.minio.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class MinioUtil {

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioConfiguration configuration;

    /**
     * @description: 获取上传临时签名
     */
    public Map getPolicy(String fileName, ZonedDateTime time) {
        PostPolicy postPolicy = new PostPolicy(configuration.getBucketName(), time);
        postPolicy.addEqualsCondition("key", fileName);
        try {
            Map<String, String> map = minioClient.getPresignedPostFormData(postPolicy);
            HashMap<String, String> map1 = new HashMap<>();
            map.forEach((k, v) -> {
                map1.put(k.replaceAll("-", ""), v);
            });
            map1.put("host", configuration.getUrl() + "/" + configuration.getBucketName());
            return map1;
        } catch (Exception e) {
            log.error("获取上传临时签名出错：{}", e.getMessage());
            throw  new RuntimeException(e.getMessage());

        }
    }

    /**
     * @description: 获取上传文件的url
     */
    public String getPolicyUrl(String objectName, Method method, int time, TimeUnit timeUnit) {
        try {
            return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(method)
                    .bucket(configuration.getBucketName())
                    .object(objectName)
                    .expiry(time, timeUnit).build());
        } catch (Exception e) {
            log.error("获取上传文件的url出错：{}", e.getMessage());
            throw  new RuntimeException(e.getMessage());
        }
    }

    /**
     * 检查bucket是否存在
     *
     * @param bucketName
     * @return
     */
    public Boolean bucketExists(String bucketName) {
        Boolean found;
        try {
            found = minioClient
                    .bucketExists(BucketExistsArgs.builder()
                            .bucket(bucketName)
                            .build());
        } catch (Exception e) {
            log.error("检查是否存在bucket出错：{}", e.getMessage());
            return false;
        }
        return found;
    }

    /**
     * 创建存储bucket
     * @return Boolean
     */
    public Boolean makeBucket(String bucketName) {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            log.error("创建存储bucket出错：{}",e.getMessage());
            return false;
        }
        return true;
    }


    /**
     * @description: 上传文件
     */
    public String upload(MultipartFile file, String fileName) {
        try {
            if (Strings.isBlank(fileName)) {
                throw new RuntimeException("文件名不能为空！");
            }
            if(!bucketExists(configuration.getBucketName())){
               if(!makeBucket(configuration.getBucketName())){
                throw new RuntimeException("创建存储bucket出错！");
               }
            }
            fileName = UUID.randomUUID().toString(true) + fileName;
            String objectName = DateUtil.format(new Date(), "YYYYMM") + "/" + fileName;

            InputStream inputStream = file.getInputStream();
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(configuration.getBucketName())
                    .object(objectName)
                    .stream(inputStream, file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build());
            return objectName;
        } catch (Exception e) {
            log.error("上传文件出错：{}", e.getMessage());
           throw  new RuntimeException(e.getMessage());
        }
    }

    /**
     * @description: 根据filename获取文件访问地址
     */
    public String getUrl(String objectName, int time, TimeUnit timeUnit) {
        String url = null;
        try {
            url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(Method.GET)
                    .bucket(configuration.getBucketName())
                    .object(objectName)
                    .expiry(time, timeUnit).build());
        } catch (Exception e) {
            log.error("根据filename获取文件访问地址出错：{}", e.getMessage());
            throw  new RuntimeException(e.getMessage());
        }
        return url;
    }

}
